﻿#region Usings

using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using DbConvertor.Helpers;

#endregion

namespace DbConvertor.Data
{
    public static class QueryUtils
    {
        #region Domestic queries

        public static Func<ModelContainer, bool, int, IEnumerable<DomesticPrice>> GetDomesticPrices
        {
            get
            {
                return CompiledQuery.Compile<ModelContainer, bool, int, IEnumerable<DomesticPrice>>(
                    (context, isDomesticOnly, distance) => context.DomesticPrices.Where(
                        p =>
                        p.TarifNumber == 1 && p.Ru == "0" &&
                        (p.Class == Constants.FirstClassNumber || p.Class == Constants.SecondClassNumber) &&
                        p.TrainType == (isDomesticOnly ? 0 : 1) && p.RoundTrip == "0" &&
                        p.ZoneFrom <= distance && p.ZoneTo >= distance &&
                        p.ValidFrom <= DateTime.Now && p.ValidTo >= DateTime.Now)
                    );
            }
        }

        #endregion

        #region International queries

        public static Func<ModelContainer, string, string, IEnumerable<string>, TcvRelation> GetRelation
        {
            get
            {
                var relNumber = CompiledQuery.Compile<ModelContainer, string, string, IEnumerable<string>, IEnumerable<string>>(
                    (context, borderEva, lastEva, allStations) => context.TcvRels.Join(context.TcvDests,
                                                                 border => border.RelationNumber,
                                                                 destination => destination.RelationNumber,
                                                                 (border, destination) => new { border, destination })
                                                                 .Where(pair => (pair.border.BorderStation == borderEva && pair.destination.DestinationStation == lastEva) ||
                                                                                (pair.border.BorderStation == lastEva && pair.destination.DestinationStation == borderEva))
                                                            .Join(context.TcvVias,
                                                                 pair => pair.border.RelationNumber,
                                                                 via => via.RelationNumber,
                                                                 (pair, via) => new { pair.border, via, pair.destination }
                                                            )
                                                            .Where(all => all.border.ValidFrom <= DateTime.Now && all.border.ValidTo >= DateTime.Now &&
                                                                          all.destination.ValidFrom <= DateTime.Now && all.destination.ValidTo >= DateTime.Now &&
                                                                          all.via.ValidFrom <= DateTime.Now && all.via.ValidTo >= DateTime.Now &&
                                                                          ((all.via.Included.Value && allStations.Contains(all.via.ViaStation)) ||
                                                                           (!all.via.Included.Value && !allStations.Contains(all.via.ViaStation)))
                                                            ).Select(all => all.via.RelationNumber).Distinct());
                return CompiledQuery.Compile<ModelContainer, string, string, IEnumerable<string>, TcvRelation>
                    (
                        (context, borderEva, lastEva, allStations) =>
                            context.TcvRelationen.SingleOrDefault(r => r.RelationNumber == relNumber(context, borderEva, lastEva, allStations).FirstOrDefault())
                    );
            }
        }

        public static Func<ModelContainer, TcvRelation, IEnumerable<Tcvp>> GetTcvpForRelation
        {
            get
            {
                return
                    CompiledQuery.Compile<ModelContainer, TcvRelation, IEnumerable<Tcvp>>(
                        (context, tcvRelation) => context.Tcvps.Where(
                            p =>
                            ((tcvRelation.Ru1 != "0" && p.Ru == tcvRelation.Ru1 && p.ZoneFrom <= tcvRelation.Distance1 && p.ZoneTo >= tcvRelation.Distance1) ||
                             (tcvRelation.Ru2 != "0" && p.Ru == tcvRelation.Ru2 && p.ZoneFrom <= tcvRelation.Distance2 && p.ZoneTo >= tcvRelation.Distance2) ||
                             (tcvRelation.Ru3 != "0" && p.Ru == tcvRelation.Ru3 && p.ZoneFrom <= tcvRelation.Distance3 && p.ZoneTo >= tcvRelation.Distance3) ||
                             (tcvRelation.Ru0 != "0" && p.Ru == tcvRelation.Ru0 && p.ZoneFrom <= tcvRelation.Distance0 && p.ZoneTo >= tcvRelation.Distance0))
                            && p.TarifNumber == 1 &&
                            p.ValidFrom <= DateTime.Now && p.ValidTo >= DateTime.Now));
            }
        }

        public static Func<ModelContainer, TcvRelation, IEnumerable<TcvSerie>> GetTcvSerialForRelation
        {
            get
            {
                return
                    CompiledQuery.Compile<ModelContainer, TcvRelation, IEnumerable<TcvSerie>>(
                        (context, tcvRelation) => context.TcvSerien.Where(
                            p =>
                            ((tcvRelation.SerialPrice1 != 0 && tcvRelation.Ru1 != "0" && p.Serial == tcvRelation.SerialPrice1 && p.Ru == tcvRelation.Ru1) ||
                             (tcvRelation.SerialPrice2 != 0 && tcvRelation.Ru2 != "0" && p.Serial == tcvRelation.SerialPrice2 && p.Ru == tcvRelation.Ru2) ||
                             (tcvRelation.SerialPrice3 != 0 && tcvRelation.Ru3 != "0" && p.Serial == tcvRelation.SerialPrice3 && p.Ru == tcvRelation.Ru3) ||
                             (tcvRelation.SerialPrice0 != 0 && tcvRelation.Ru0 != "0" && p.Serial == tcvRelation.SerialPrice0 && p.Ru == tcvRelation.Ru0)) &&
                            p.TarifNumber == 1 &&
                            p.ValidFrom <= DateTime.Now && p.ValidTo >= DateTime.Now));
            }
        }

        #endregion
    }
}